﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Snowdreamist.Text.UBB
{
    /// <summary>
    /// UBB content type
    /// </summary>
    public enum UBBContentType
    {
        Text,
        StartLabel,
        CloseLabel
    }

    /// <summary>
    /// UBB content
    /// </summary>
    public class UBBContent
    {
        /// <summary>
        /// Is the text probably a start label
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public static bool IsStartLabelText(string text)
        {
            if (text == null)
                throw new ArgumentNullException("text");
            return text.Length >= 2 && text[0] == '[' && text[1] != '/' && text[text.Length - 1] == ']';
        }

        /// <summary>
        /// Is the text probably a close label
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public static bool IsCloseLabelText(string text)
        {
            if (text == null)
                throw new ArgumentNullException("text");
            return text.Length >= 3 && text[0] == '[' && text[1] == '/' && text[text.Length - 1] == ']';
        }

        /// <summary>
        /// ctor
        /// </summary>
        /// <param name="text"></param>
        public UBBContent(string text) : this(text, true, null) { }

        /// <summary>
        /// UBB ctor
        /// </summary>
        /// <param name="text"></param>
        public UBBContent(string text, bool isText, IUBBElementFactory factory)
        {
            if (text == null)
                throw new ArgumentNullException("text");

            this._text = text;

            if (isText)
            {
                this.Type = UBBContentType.Text;
            }
            else
            {
                if (IsStartLabelText(text))
                    this.Type = UBBContentType.StartLabel;
                else if (IsCloseLabelText(text))
                    this.Type = UBBContentType.CloseLabel;
                else
                    this.Type = UBBContentType.Text;
            }

            // All content's display type is Text by default
            this.DisplayType = UBBContentType.Text;

            this.Factory = factory;
        }

        public UBBElement Create()
        {
            return this.Factory.Create(this);
        }

        /// <summary>
        /// Factory for this element (if a label)
        /// </summary>
        public IUBBElementFactory Factory { get; private set; }

        /// <summary>
        /// The type
        /// Label Original type which comes from pure text analysis without label match information
        /// (NOTE: The type of a content may change when matching ubb labels
        /// </summary>
        public UBBContentType Type { get; private set; }

        /// <summary>
        /// Display type
        /// The final display ubb content type after ubb label match
        /// </summary>
        public UBBContentType DisplayType { get; set; }

        /// <summary>
        /// Get the text
        /// Based on the type
        /// </summary>
        /// <returns></returns>
        public string Text
        {
            get
            {
                if (this.Type == UBBContentType.StartLabel && IsStartLabelText(this._text))
                {
                    return this._text.Substring(1, this._text.Length - 2);
                }
                else if (this.Type == UBBContentType.CloseLabel && IsCloseLabelText(this._text))
                {
                    return this._text.Substring(2, this._text.Length - 3);
                }
                else
                {
                    return this._text;
                }
            }
        }

        /// <summary>
        /// Display text
        /// For display, all content are the same
        /// </summary>
        public string DisplayText
        {
            get
            {
                return this._text;
            }
        }

        /// <summary>
        /// Get Label name without parameters
        /// </summary>
        /// <returns></returns>
        public string GetLabelName()
        {
            if (this.Type == UBBContentType.Text)
                throw new InvalidOperationException("Content type is not Label");
            var text = this.Text;
            var equalIndex = text.IndexOf('=');
            if (equalIndex == -1)
                return text;
            else
                return text.Substring(0, equalIndex);
        }

        #region private

        private string _text;

        #endregion private
    }
}